﻿using ModuleBase.googoltech.GTS;
using ModuleBase;
using Newtonsoft.Json;
using Prism.Ioc;
using System.Collections;
using System.Diagnostics;
using GeneralMotionControlProject.Vision.Models;
using HalconDotNet;

namespace PhotoTheProduct
{
    public class PhotoTheProduct : ModuleBase.ModuleBase
    {
        private IAxisCardService _axisCardService;
        private ModuleStateService _moduleStateService;
        bool outputs = false;
        private IContainerProvider containerProvider;
        private IHIKCameraService camera;
        Stopwatch sw = new Stopwatch();
        Queue<XYZPoint> pointsQueue = new Queue<XYZPoint>();
        HObject img = null;
        bool cameraGrabDone = false;
        private readonly MVisionFunctions mVisionFunctions;
        HTuple calibMat;
        XYZPoint curPoint = new XYZPoint();


        private object _parameter1;
        public object Parameter1
        {
            get => _parameter1;
            set
            {
                if (_parameter1 != value)
                {
                    _parameter1 = value;
                    OnPropertyChanged(nameof(Parameter1));
                }
            }
        }
        private double _parameter2;
        public double Parameter2
        {
            get => _parameter2;
            set
            {
                if (_parameter2 != value)
                {
                    _parameter2 = value;
                    OnPropertyChanged(nameof(Parameter2));
                }
            }
        }
        private double _parameter3;
        public double Parameter3
        {
            get => _parameter3;
            set
            {
                if (_parameter3 != value)
                {
                    _parameter3 = value;
                    OnPropertyChanged(nameof(Parameter3));
                }
            }
        }
        private double _parameter4;
        public double Parameter4
        {
            get => _parameter4;
            set
            {
                if (_parameter4 != value)
                {
                    _parameter4 = value;
                    OnPropertyChanged(nameof(Parameter4));
                }
            }
        }
        private double _parameter5;
        public double Parameter5
        {
            get => _parameter5;
            set
            {
                if (_parameter5 != value)
                {
                    _parameter5 = value;
                    OnPropertyChanged(nameof(Parameter5));
                }
            }
        }
        public override Dictionary<string, object> GetProperties()
        {
            return new Dictionary<string, object>
            {
                { "位置", Parameter1 },
                { "X轴号", Parameter2 },
                { "Y轴号", Parameter3 },
                { "X速度", Parameter4 },
                { "Y速度", Parameter5 },
            };
        }

        public override Dictionary<string, List<object>> PropertyOptions { get; } = new Dictionary<string, List<object>>
        {
            { "位置", new List<object> { "左", "右" } },
            { "X轴号", new List<object>{ 1,2,3,4,5,6,7,8 } },
            { "Y轴号", new List<object>{ 1,2,3,4,5,6,7,8 } }
        };

        public PhotoTheProduct(IAxisCardService axisCardService, ModuleStateService moduleStateService)
        {
            _axisCardService = axisCardService;
            Name = "拍产品";

            DisplayNameToPropertyNameMap = new Dictionary<string, string>
            {
                { "位置", nameof(Parameter1) },
                { "X轴", nameof(Parameter2) },
                { "Y轴", nameof(Parameter3) },
                { "X速度", nameof(Parameter4) },
                { "Y速度", nameof(Parameter5) },
            };
        }

        public override bool Execute()
        {
            Status = ModuleStatus.Executing; // 设置状态为执行中
            AxisParm _axisX = GetAxisByNumber((int)Parameter2);
            AxisParm _axisY = GetAxisByNumber((int)Parameter3);
            var photoPositionY = 0.0;
            var photoPositionX = 0.0;
            HTuple offsetX = new HTuple(0);
            HTuple offsetY = new HTuple(0);
            using var mdb = containerProvider.Resolve<MDbContext>();
            int handIndex = 0;
            if (Parameter1.ToString() == "左")
            {
                handIndex = 0;
            }
            else
            {
                handIndex = 1;
            }
            try
            {
                if (pointsQueue.Count == 0)
                {
                    var points = mdb.XYZPoints.Where(p => p.Hand == handIndex && p.IsUse).OrderBy(p => p.PcsOrder);
                    if (points.Any())
                    {
                        points.ToList().ForEach(p =>
                        {
                            pointsQueue.Enqueue(p);
                        });
                    }
                }
                if (pointsQueue.TryPeek(out var _pcs))
                {
                    curPoint = _pcs;
                }
                int stepNum = -3;
                while (true)
                {
                    var diport = GTSCard.GetDiPort1((short)_axisY.CardNo);
                    var bitArray = new BitArray(new[] { diport });
                    switch (stepNum)
                    {
                        case -3:
                            var _mParam = mdb.MParams.FirstOrDefault(x => x.Name == "IsWorking" && x.Hand == handIndex);
                            if (_mParam != null)
                            {
                                stepNum = -2;
                            }
                            break;
                        case -2:
                            if (!_moduleStateService.IsStopped)
                            {
                                GTSCard.ServoOn(_axisX);
                                GTSCard.ServoOn(_axisY);

                                sw.Restart();
                                stepNum = -1;
                            }
                            break;
                        case -1:
                            if (!_moduleStateService.IsStopped)
                            {
                                if (sw.Elapsed.TotalSeconds > 0.5)
                                {
                                    sw.Stop();
                                    GTSCard.AxisPosSet(_axisX, GTSCard.GetEnc(_axisX));
                                    GTSCard.AxisPosSet(_axisY, GTSCard.GetEnc(_axisY));
                                    stepNum = 0;
                                }
                            }
                            break;
                        // 1. XY轴移动到拍照位
                        case 0:
                            if (!_moduleStateService.IsStopped)
                            {
                                GTSCard.AxisPosMove(ref _axisX, curPoint.X + curPoint.X1, Parameter4);
                                GTSCard.AxisPosMove(ref _axisY, curPoint.Y + curPoint.Y1, Parameter5);
                                stepNum = 1;
                            }
                            break;
                        // 检查XY轴到位
                        case 1:
                            if (!_moduleStateService.IsStopped)
                            {
                                if (GTSCard.AxisPosMoveCheckDone(_axisY) && GTSCard.AxisPosMoveCheckDone(_axisX))
                                {
                                    stepNum = 2;
                                }
                            }
                            else
                            {
                                GTSCard.AxisStop(_axisX, 0);
                                GTSCard.AxisStop(_axisY, 0);
                                stepNum = 0;
                            }
                            break;
                        // 2. 触发上相机拍照
                        case 2:
                            if (!_moduleStateService.IsStopped)
                            {
                                Task.Run(() =>
                                {
                                    camera.SetTriggerMode(0);
                                    camera.SetExposureTime(1000);
                                    camera.StartGrabe();
                                    cameraGrabDone = true;
                                });
                                sw.Restart();
                                stepNum = 3;
                            }
                            break;
                        // 3. 检查拍照完成
                        case 3:
                            if (!_moduleStateService.IsStopped)
                            {
                                if (cameraGrabDone || sw.Elapsed.TotalSeconds > 1.0)
                                {
                                    sw.Stop();
                                    if (img != null && !img.IsInitialized())
                                    {
                                        VisionAction("alignment_script", img, out var row, out var col, out var angle,
                                                    out var result, out var region, out var additionalMessage);

                                        if (result.I == 1 && row.TupleLength() > 0 && col.TupleLength() > 0 && angle.TupleLength() > 0) // 识别成功
                                        {
                                            HOperatorSet.AffineTransPoint2d(calibMat, row, col, out offsetX, out offsetY);
                                        }
                                        img.Dispose(); // 立即释放图像
                                    }
                                    cameraGrabDone = false;
                                    stepNum = 4;
                                }
                            }
                            break;
                        case 4:
                            if (!_moduleStateService.IsStopped)
                            {
                                GTSCard.AxisPosMove(ref _axisX, offsetX.D, Parameter4);
                                GTSCard.AxisPosMove(ref _axisY, offsetY.D, Parameter5);
                                stepNum = 5;
                            }
                            break;
                        case 6:
                            pointsQueue.Dequeue(); // 移除已处理点
                            outputs = true;
                            return outputs;
                    }
                }
            }
            catch (Exception exp)
            {
                outputs = false;
            }
            return outputs;
        }

        public override async Task<bool> ExecuteAsync()
        {
            var result = await Task.Run(() => Execute());
            return result;
        }

        public override void Initialize()
        {

        }
        private AxisParm GetAxisByNumber(int axisNumber)
        {
            switch (axisNumber)
            {
                case 1: return _axisCardService.A1;
                case 2: return _axisCardService.A2;
                case 3: return _axisCardService.A3;
                case 4: return _axisCardService.A4;
                case 5: return _axisCardService.A5;
                case 6: return _axisCardService.A6;
                case 7: return _axisCardService.A7;
                case 8: return _axisCardService.A8;
                default: return _axisCardService.A1;
            }
        }
        private void VisionAction(string procedureName, HObject img, out HTuple row,
        out HTuple column, out HTuple angle, out HTuple result, out HObject r_region, out string additionalMessage)
        {
            result = new HTuple(0);
            try
            {
                VisionProgramDisp disp = JsonConvert.DeserializeObject<VisionProgramDisp>(procedureName);
                int id = disp.Id;
                HTuple hv_row = new HTuple(0), hv_column = new HTuple(0), hv_angle = new HTuple(0), hv_score = new HTuple(0), v1 = new HTuple(0), v2 = new HTuple(0);
                string msg = string.Empty;
                HObject eImage = img.CopyObj(1, -1);
                HObject ngRegion, resultRegion;
                HOperatorSet.GenEmptyRegion(out ngRegion);
                HOperatorSet.GenEmptyRegion(out resultRegion);
                HOperatorSet.GenEmptyRegion(out r_region);
                bool r1 = true;
                var mdb = containerProvider.Resolve<MDbContext>();
                var projects = mdb.VisionProjects.Where(pro => pro.ProgramId == id).OrderBy(pro => pro.PcsOrder);
                if (projects.Any())
                {
                    var mprojects = projects.ToList();
                    foreach (var project in mprojects)
                    {
                        if (!r1)
                        {
                            break;
                        }
                        var _function = mVisionFunctions.VisionFunctions.FirstOrDefault(func => func.Id == project.FunctionId);
                        if (_function != null)
                        {
                            HObject SelectedRegion;
                            HOperatorSet.GenEmptyObj(out SelectedRegion);
                            r1 = mVisionFunctions.FunDictionary[_function.Name].Run(ref eImage, project.Parameter, ref hv_row, ref hv_column, ref hv_angle, ref hv_score, ref ngRegion, ref SelectedRegion, ref v1, ref v2, ref msg);
                            if (project.IsDisplayRegion)
                            {
                                HOperatorSet.Union2(resultRegion, SelectedRegion.CopyObj(1, -1), out resultRegion);
                            }
                            SelectedRegion.Dispose();
                        }
                        else
                        {
                            r1 = false;
                        }
                    }

                }
                if (r1)
                {
                    result = new HTuple(1);
                    row = hv_row;
                    column = hv_column;
                    angle = hv_angle;
                    r_region = resultRegion.CopyObj(1, -1);
                }
                else
                {
                    result = new HTuple(0);
                    row = new HTuple(0);
                    column = new HTuple(0);
                    angle = new HTuple(0);
                }
                additionalMessage = msg;
                eImage.Dispose();
                ngRegion.Dispose();
                resultRegion.Dispose();
            }
            catch (Exception ex)
            {
                result = new HTuple(0);
                row = new HTuple(0);
                column = new HTuple(0);
                angle = new HTuple(0);
                HOperatorSet.GenEmptyRegion(out r_region);
                additionalMessage = string.Empty;
            }

        }
        public class VisionProgramDisp
        {
            public int Id { get; set; }
            public string Name { get; set; }
        }
        /*
        /// <summary>
        /// 飞拍
        /// </summary>
        /// <param name="token"></param>
        private void GrabAction(CancellationToken token)
        {
            #region 变量
            int stepnum = 500;
            Queue<FlyGrabPoint> GrabPointQueue = new Queue<FlyGrabPoint>();
            FlyGrabPoint GrabPoint = new FlyGrabPoint();
            Stopwatch sw = new Stopwatch();
            bool GrabDone = false;
            bool GrabResutl = false;
            bool FlyFinish = false;
            FlyGrabPoint[] PathFlyGrabPoint = new FlyGrabPoint[0];
            int[] Buf1 = new int[0], Buf2 = new int[0];
            int ImageCount = 0;
            int trackCount = 0;
            bool imageFailDone = false;
            using var mdb = containerProvider.Resolve<MDbContext>();
            var _mParam = mdb.MParams.FirstOrDefault(m => m.Name == "CameraExposureTime" && m.Hand == handindex);
            if (_mParam != null)
            {
                CameraExposureTime = double.Parse(_mParam.Value);
            }
            #endregion
            _axisCardService.ImageList.Clear();
            while (true)
            {
                if (token.IsCancellationRequested)
                {
                    return;
                }
                try
                {
                    switch (stepnum)
                    {
                        #region 单拍
                        case 500:
                            if (!_moduleStateService.IsStopped)
                            {
                                GrabPointQueue.Clear();
                                var grabpoints = mdb.FlyGrabPoints.Where(f => f.Hand == handindex && f.Kind == 0).OrderBy(f => f.PcsOrder);
                                if (grabpoints.Any())
                                {
                                    grabpoints.ToList().ForEach(p =>
                                    {
                                        GrabPointQueue.Enqueue(p);
                                    });
                                }
                                stepnum = 501;
                            }
                            break;
                        case 501:
                            if (!_moduleStateService.IsStopped)
                            {
                                if (GrabPointQueue.TryPeek(out var p))
                                {
                                    if (GrabPointQueue.TryPeek(out p))
                                    {
                                        GrabPoint = GrabPointQueue.Dequeue();
                                    }
                                    else
                                    {
                                        GrabPoint = new FlyGrabPoint
                                        {
                                            Id = -1,
                                            X = InitPoint.X,
                                            Y = InitPoint.Y,
                                            Z = InitPoint.Z,
                                            UseLight1 = true,
                                            UseLight2 = true
                                        };
                                    }
                                    stepnum = 502;
                                }
                                else
                                {
                                    stepnum = 600;
                                }
                            }
                            break;
                        case 502:
                            if (!_moduleStateService.IsStopped)
                            {
                                GTSCard.AxisPosMove(ref _axisY, GrabPoint.Y, Parameter4);
                                stepnum = 503;
                            }
                            break;
                        case 503:
                            if (!_moduleStateService.IsStopped)
                            {
                                if (GTSCard.AxisPosMoveCheckDone(_axisY))
                                {
                                    sw.Restart();
                                    stepnum = 504;
                                }
                            }
                            else
                            {
                                GTSCard.AxisStop(_axisY, 0);
                                stepnum = 502;
                            }
                            break;
                        case 504:
                            if (!_moduleStateService.IsStopped)
                            {
                                if (sw.Elapsed.TotalSeconds > Parameter6)
                                {
                                    stepnum = 505;
                                }
                            }
                            break;
                        case 505:
                            if (!_moduleStateService.IsStopped)
                            {
                                GrabResutl = true;
                                if (GrabPoint.Id > 0)
                                {
                                    GrabDone = false;
                                    camera.ImageQueue.Clear();
                                    camera.SetTriggerMode(0);
                                    camera.SetExposureTime((float)CameraExposureTime);
                                    camera.StartGrabe();
                                    Task.Run(async () =>
                                    {
                                        bool breakFlag = false;
                                        Task task = new Task(() =>
                                        {
                                            int mIndex = 0;
                                            while (mIndex < 1 && !breakFlag)
                                            {
                                                HObject? hObj;
                                                if (camera.ImageQueue.TryPeek(out hObj))
                                                {
                                                    camera.ImageQueue.TryDequeue(out hObj);
                                                    _axisCardService.ImageList.Add(new FlyImage
                                                    {
                                                        CameraHand = 0,
                                                        MImage = hObj,
                                                        Track = 0,
                                                        ImagePcsOrder = GrabPoint.PcsOrder,
                                                        Kind = GrabPoint.Kind
                                                    });
                                                    mIndex++;
                                                }
                                            }
                                        });
                                        task.Start();
                                        var delay = Task.Delay(3000);
                                        if (await Task.WhenAny(task, delay) == delay)
                                        {
                                            GrabResutl = false;
                                            breakFlag = true;
                                        }
                                        camera.StopGrabe();

                                    }).ContinueWith(t => { GrabDone = true; });
                                }
                                else
                                {
                                    GrabDone = true;
                                }
                                stepnum = 506;
                            }
                            break;
                        case 506:
                            if (GrabDone)
                            {
                                GrabDone = false;
                                if (!GrabResutl)
                                {
                                    string alarmstr = string.Empty;
                                    if (!GrabResutl)
                                    {
                                        alarmstr += "相机拍照失败";
                                    }
                                    imageFailDone = false;
                                    stepnum = 507;
                                }
                                else
                                {
                                    stepnum = 501;
                                }
                            }
                            break;
                        case 507:
                            if (!_moduleStateService.IsStopped)
                            {
                                if (imageFailDone)
                                {
                                    imageFailDone = false;
                                    stepnum = 505;
                                }
                            }
                            break;
                        #endregion
                        #region 飞拍

                        case 600:
                            if (!_moduleStateService.IsStopped)
                            {
                                FlyFinish = false;

                                var pathFlyPoints = mdb.FlyGrabPoints.Where(f => f.Hand == handindex && f.Kind == 2 && f.Track == trackCount).OrderBy(f => f.PcsOrder);
                                if (pathFlyPoints.Any())
                                {
                                    PathFlyGrabPoint = pathFlyPoints.ToArray();
                                    var flyPoints = mdb.FlyGrabPoints.Where(f => f.Hand == handindex && f.Kind == 1 && f.Track == trackCount).OrderBy(f => f.PcsOrder);
                                    if (flyPoints.Any())
                                    {
                                        var pointArr = flyPoints.ToArray();
                                        ImageCount = pointArr.Length;
                                        Buf1 = new int[pointArr.Length];
                                        double cameraGrabMovSpace = pointArr[0].Y > pointArr[pointArr.Length - 1].Y ? Parameter5 / 1000 * Parameter4 : Parameter5 / 1000 * Parameter4 * -1;
                                        for (int i = 0; i < pointArr.Length; i++)
                                        {
                                            Buf1[i] = (int)((pointArr[i].Y - PathFlyGrabPoint[0].Y + cameraGrabMovSpace) / _axisY.Equiv);
                                        }
                                    }
                                    else
                                    {
                                        ImageCount = 0;
                                    }
                                }
                                else
                                {
                                    FlyFinish = true;
                                }
                                if (FlyFinish)
                                {
                                    return;//飞拍完成
                                }
                                else
                                {
                                    stepnum = 601;
                                }
                            }
                            break;


                        case 601:
                            if (!_moduleStateService.IsStopped)
                            {
                                if (!FlyFinish)
                                {
                                    GTSCard.AxisPosMove(ref _axisY, PathFlyGrabPoint[0].Y, Parameter4);
                                }
                                else
                                {
                                    GTSCard.AxisPosMove(ref _axisY, InitPoint.Y, Parameter4);
                                }
                                stepnum = 602;
                            }
                            break;
                        case 602:
                            if (!_moduleStateService.IsStopped)
                            {
                                if (GTSCard.AxisPosMoveCheckDone(_axisY))
                                {
                                    sw.Restart();
                                    stepnum = 603;
                                }
                            }
                            else
                            {
                                GTSCard.AxisStop(_axisY, 0);
                                stepnum = 601;
                            }
                            break;
                        case 603:
                            if (!_moduleStateService.IsStopped)
                            {
                                if (sw.Elapsed.TotalSeconds > Parameter6)
                                {
                                    stepnum = 604;
                                }
                            }
                            break;
                        case 604:
                            if (!_moduleStateService.IsStopped)
                            {
                                if (ImageCount > 0)
                                {
                                    GTSCard.AxisCompareUse1(0, _axisY.AxisId, Buf1);//设置飞拍数据

                                    camera.ImageQueue.Clear();
                                    camera.SetExposureTime((float)CameraExposureTime);
                                    camera.SetTriggerMode(1);
                                    camera.StartGrabe();
                                }
                                stepnum = 605;
                            }
                            break;
                        case 605:
                            if (!_moduleStateService.IsStopped)
                            {
                                if (!FlyFinish)
                                {
                                    GTSCard.AxisPosMove(ref _axisY, PathFlyGrabPoint[1].Y, Parameter4);
                                }
                                else
                                {
                                    GTSCard.AxisPosMove(ref _axisY, InitPoint.Y, Parameter4);
                                }
                                stepnum = 606;
                            }
                            break;
                        case 606:
                            if (!_moduleStateService.IsStopped)
                            {
                                if (GTSCard.AxisPosMoveCheckDone(_axisY))
                                {
                                    GrabResutl = true;
                                    int l = 0, rightl = 0;
                                    if (ImageCount > 0)
                                    {
                                        int _index = 0;
                                        var flyPoints = mdb.FlyGrabPoints.Where(f => f.Hand == handindex && f.Track == trackCount && f.Kind == 1).OrderBy(f => f.PcsOrder);
                                        var _arr = flyPoints.ToArray();
                                        camera.StopGrabe();
                                        l = camera.ImageQueue.Count;
                                        if (camera.ImageQueue.Count >= _arr.Length)
                                        {
                                            while (camera.ImageQueue.TryDequeue(out var _img))
                                            {
                                                //先查有没有拍过
                                                var _imgrecord = _axisCardService.ImageList.FirstOrDefault(img => img.CameraHand == handindex && img.Kind == 1 && img.Track == trackCount && img.ImagePcsOrder == _arr[_index].PcsOrder);
                                                if (_imgrecord == null)
                                                {
                                                    _axisCardService.ImageList.Add(new FlyImage
                                                    {
                                                        CameraHand = 0,
                                                        MImage = _img,
                                                        Track = trackCount,
                                                        ImagePcsOrder = _arr[_index].PcsOrder,
                                                        Kind = 1
                                                    });
                                                }
                                                else
                                                {
                                                    //拍过→更新
                                                    _imgrecord.MImage.Dispose();
                                                    _imgrecord.MImage = _img;
                                                }
                                                _index++;
                                            }
                                        }
                                        else
                                        {
                                            //图片长度不对
                                            GrabResutl = false;
                                        }
                                    }
                                    if (GrabResutl)
                                    {
                                        trackCount++;
                                        stepnum = 600;
                                    }
                                    else
                                    {
                                        string alarmstr = string.Empty;
                                        if (!GrabResutl)
                                        {
                                            string str = $"相机拍照失败:应拍{ImageCount}张，实拍{l}张";
                                            alarmstr += str;
                                        }
                                        alarmstr += "\n关闭窗口或按复位、启动按钮重新飞拍";
                                        imageFailDone = false;
                                        stepnum = 607;
                                    }
                                }
                            }
                            else
                            {
                                GTSCard.AxisStop(_axisY, 0);
                                stepnum = 605;
                            }
                            break;
                        case 607:
                            if (!_moduleStateService.IsStopped)
                            {
                                if (imageFailDone)
                                {
                                    imageFailDone = false;
                                    stepnum = 600;
                                }
                            }
                            break;
                        #endregion
                        default:
                            break;
                    }
                }
                catch { }
                System.Threading.Thread.Sleep(10);

            }
        }
        void LoadCameraParam()
        {
            try
            {
                string calibfilepath1 = "Camera\\Calib\\Left";
                string calibfilepath2 = "Camera\\Calib\\Right";

                HOperatorSet.ReadTuple(System.IO.Path.Combine(System.Environment.CurrentDirectory, calibfilepath1, "CalibHomMat2D.tup"), out calibHomMat2D1);

                HOperatorSet.ReadTuple(System.IO.Path.Combine(System.Environment.CurrentDirectory, calibfilepath2, "CalibHomMat2D.tup"), out calibHomMat2D2);

            }
            catch (Exception ex)
            {

            }
        }*/
    }
}
